package com.xiaoxin.executor.batch.listener;

import com.xiaoxin.executor.domain.EtlLogStep;
import com.xiaoxin.executor.enums.EtlStatusEnum;
import com.xiaoxin.executor.service.EtlLogStepService;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

/**
 * @Author : Zhangxx
 * @Description :step执行记录日志
 **/
@Component
public class EtlLogStepListener<I, O> implements StepExecutionListener {
	private static Logger logger = LogManager.getLogger(EtlLogStepListener.class);
	@Autowired
	private EtlLogStepService etlLogStepService;

	public void beforeStep(StepExecution stepExecution) {
		String etlLogJobId = stepExecution.getJobExecution().getExecutionContext().get("etlLogJobId") + "";
		EtlLogStep logStep = new EtlLogStep();
		logStep.setJobId(etlLogJobId);
		logStep.setJobName(stepExecution.getJobExecution().getJobInstance().getJobName());
		logStep.setStepName(stepExecution.getStepName());
		logStep.setStatus(EtlStatusEnum.STATUS1.getCode());
		logStep.setBeginTime(new Date());
		etlLogStepService.save(logStep);
		stepExecution.getExecutionContext().put("etlLogJobId", logStep.getId());

		String stepName = stepExecution.getStepName();
		logger.info("Step {} start. ETL_LOG_JOB.ID:{}", stepName, etlLogJobId);
	}

	public ExitStatus afterStep(StepExecution stepExecution) {
		String etlLogJobId = stepExecution.getJobExecution().getExecutionContext().get("etlLogJobId") + "";
		String etlLogStepId = stepExecution.getJobExecution().getExecutionContext().get("etlLogJobId") + "";

		EtlLogStep logStep = new EtlLogStep();
		logStep.setId(etlLogStepId);
		logStep.setJobId(etlLogJobId);
		logStep.setJobName(stepExecution.getJobExecution().getJobInstance().getJobName());
		logStep.setStepName(stepExecution.getStepName());
		if (stepExecution.getStatus() == BatchStatus.COMPLETED) {
			logStep.setStatus(EtlStatusEnum.STATUS2.getCode());
		} else {
			logStep.setStatus(EtlStatusEnum.STATUS3.getCode());
			String errorMessage = getException(stepExecution.getFailureExceptions());
			logStep.setErrorMessage(errorMessage);
		}
		logStep.setEndTime(new Date());
		etlLogStepService.updateById(logStep);

		String stepName = stepExecution.getStepName();
		BatchStatus status = stepExecution.getStatus();
		logger.info("Step {} {}. ETL_LOG_JOB.ID:{}", stepName, status, etlLogStepId);
		return null;
	}

	private String getException(List<Throwable> failureExceptions) {
		if (CollectionUtils.isEmpty(failureExceptions)) {
			return StringUtils.EMPTY;
		}
		StringBuffer errorMessage = new StringBuffer();
		for (Throwable exception : failureExceptions) {
			errorMessage.append(exception.getClass().getName() + " : " + exception.getMessage() + "\n");
			for (StackTraceElement stackTraceElement : exception.getStackTrace()) {
				errorMessage.append(stackTraceElement.toString() + "\n");
			}
		}
		return errorMessage.toString();
	}

}
